package copyengine.network.serverAgent.impl.socket
{
    import copyengine.log.CELog;
    import copyengine.network.serverAgent.impl.socket.dataHandle.IServerAgentSocketConnectorDataHandle;
    import copyengine.network.serverAgent.impl.socket.exceptionHandle.ISocketServerAgentExceptionHandle;
    import copyengine.network.serverAgent.receiver.INetworkDataReceiver;
    import copyengine.network.serverAgent.sender.INetworkDataSender;
    import copyengine.utils.GeneralUtils;

    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.Socket;
    import flash.utils.ByteArray;

    /**
     * 使用Socket方式和服务器进行连接 该类本身既是INetworkDataReceiver又是INetworkDataSender
     *
     * 其中
     * ISocketServerAgentExceptionHandle 用于处理Socket连接时候抛出的异常逻辑
     * IServerAgentSocketConnectorDataHandle 用于处理Socket收到的二进制数据(解包,断包,粘包)
     */
    public class CEServerAgentSocketConnector implements INetworkDataReceiver, INetworkDataSender
    {
        private var mSocket:Socket;
        private var mHost:String;
        private var mPort:int;
        private var mExceptionHandle:ISocketServerAgentExceptionHandle;
        private var mDataHandle:IServerAgentSocketConnectorDataHandle;

        private var mOnSocketConnectCallback:Function;

        public function CEServerAgentSocketConnector(_host:String, _port:int,
                                                     _exceptionHandle:ISocketServerAgentExceptionHandle,
                                                     _socketDataHandle:IServerAgentSocketConnectorDataHandle) {
            mHost = _host;
            mPort = _port;
            mSocket = new Socket();
            mExceptionHandle = _exceptionHandle;
            mDataHandle = _socketDataHandle;
            addListener();
        }

        public function connect(_onConnectCallback:Function):void {
            mOnSocketConnectCallback = _onConnectCallback;
            mSocket.connect(mHost, mPort);
        }

        public function set onReceiveServerDataCallback(_callback:Function):void {mDataHandle.onReceiveServerDataCallback = _callback;}

        public function setDataToServer(_data:ByteArray):void {
            mSocket.writeBytes(_data);
            mSocket.flush();
        }

        public function dispose():void {
            if (mSocket != null) {
                removeListener();
                mSocket.close();
                mSocket = null;
            }
        }

        private function addListener():void {
            GeneralUtils.addTargetEventListener(mSocket, Event.CLOSE, onSocketCloseHandler);
            GeneralUtils.addTargetEventListener(mSocket, Event.CONNECT, onSocketConnectHandler);
            GeneralUtils.addTargetEventListener(mSocket, IOErrorEvent.IO_ERROR, onSocketIOErrorHandler);
            GeneralUtils.addTargetEventListener(mSocket, SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityErrorHandler);
            GeneralUtils.addTargetEventListener(mSocket, ProgressEvent.SOCKET_DATA, onSocketReceiveDataHandler);
        }

        private function removeListener():void {
            GeneralUtils.removeTargetEventListener(mSocket, Event.CLOSE, onSocketCloseHandler);
            GeneralUtils.removeTargetEventListener(mSocket, Event.CONNECT, onSocketConnectHandler);
            GeneralUtils.removeTargetEventListener(mSocket, IOErrorEvent.IO_ERROR, onSocketIOErrorHandler);
            GeneralUtils.removeTargetEventListener(mSocket, SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityErrorHandler);
            GeneralUtils.removeTargetEventListener(mSocket, ProgressEvent.SOCKET_DATA, onSocketReceiveDataHandler);
        }

        private function onSocketCloseHandler(e:Event):void {mExceptionHandle.onSocketDisconnect(e);}

        private function onSocketIOErrorHandler(e:IOErrorEvent):void {mExceptionHandle.onSocketIOError(e);}

        private function onSocketSecurityErrorHandler(e:SecurityErrorEvent):void {mExceptionHandle.onSocketSecurityError(e);}

        private function onSocketConnectHandler(e:Event):void {
            CELog.log("CEServerAgentSocketConnector-> connect to server : " + mHost + " port: " + mPort);
            mOnSocketConnectCallback && mOnSocketConnectCallback();
            mOnSocketConnectCallback = null;
        }

        private function onSocketReceiveDataHandler(e:ProgressEvent):void {mDataHandle.handleData(mSocket, e);}

    }
}
